home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / gnu / nethack.lha / nethack-3.1 / src / worm.c < prev    next >
C/C++ Source or Header  |  1992-12-13  |  19KB  |  719 lines

  1. /*    SCCS Id: @(#)worm.c    3.1    91/12/30    */
  2. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
  3. /* NetHack may be freely redistributed.  See license for details. */
  4.  
  5. #include "hack.h"
  6. #include "lev.h"
  7.  
  8. #define newseg()      (struct wseg *) alloc(sizeof(struct wseg))
  9. #define dealloc_seg(wseg) free((genericptr_t) (wseg))
  10.  
  11. /* worm segment structure */
  12. struct wseg {
  13.     struct wseg *nseg;
  14.     xchar  wx, wy;    /* the segment's position */
  15. };
  16.  
  17. static void FDECL(toss_wsegs, (struct wseg *,BOOLEAN_P));
  18. static void FDECL(shrink_worm, (int));
  19. static void FDECL(random_dir, (XCHAR_P,XCHAR_P,xchar *,xchar *));
  20. static struct wseg *FDECL(create_worm_tail, (int));
  21.  
  22. /*  Description of long worm implementation.
  23.  *
  24.  *  Each monst struct of the head of a tailed worm has a wormno set to
  25.  *            1 <= wormno < MAX_NUM_WORMS
  26.  *  If wormno == 0 this does not mean that the monster is not a worm,
  27.  *  it just means that the monster does not have a long worm tail.
  28.  *
  29.  *  The actual segments of a worm are not full blown monst structs.
  30.  *  They are small wseg structs, and their position in the levels.monsters[][]
  31.  *  array is held by the monst struct of the head of the worm.  This makes
  32.  *  things like probing and hit point bookkeeping much easier.
  33.  *
  34.  *  The segments of the long worms on a level are kept as an array of
  35.  *  singly threaded linked lists.  The wormno variable is used as an index
  36.  *  for these segment arrays.
  37.  *
  38.  *  wtails:    The first (starting struct) of a linked list.  This points
  39.  *        to the tail (last) segment of the worm.
  40.  *
  41.  *  wheads:    The last (end) of a linked list of segments.  This points to
  42.  *        the segment that is at the same position as the real monster
  43.  *        (the head).  Note that the segment that wheads[wormno] points
  44.  *        to, is not displayed.  It is simply there to keep track of
  45.  *        where the head came from, so that worm movement and display are
  46.  *        simplified later.
  47.  *        Keeping the head segment of the worm at the end of the list
  48.  *        of tail segments is an endless source of confusion, but it is
  49.  *        necessary.
  50.  *        From now on, we will use "start" and "end" to refer to the
  51.  *        linked list and "head" and "tail" to refer to the worm.
  52.  *
  53.  *  One final worm array is:
  54.  *
  55.  *  wgrowtime:    This tells us when to add another segment to the worm.
  56.  *
  57.  *  When a worm is moved, we add a new segment at the head, and delete the
  58.  *  segment at the tail (unless we want it to grow).  This new head segment is
  59.  *  located in the same square as the actual head of the worm.  If we want
  60.  *  to grow the worm, we don't delete the tail segment, and we give the worm
  61.  *  extra hit points, which possibly go into its maximum.
  62.  *
  63.  *  Non-moving worms (worm_nomove) are assumed to be surrounded by their own
  64.  *  tail, and, thus, shrink instead of grow (as their tails keep going while
  65.  *  their heads are stopped short).  In this case, we delete the last tail
  66.  *  segment, and remove hit points from the worm.
  67.  */
  68.  
  69. struct wseg *wheads[MAX_NUM_WORMS]   = DUMMY, *wtails[MAX_NUM_WORMS] = DUMMY;
  70. long         wgrowtime[MAX_NUM_WORMS] = DUMMY;
  71.  
  72. /*
  73.  *  get_wormno()
  74.  *  
  75.  *  Find an unused worm tail slot and return the index.  A zero means that
  76.  *  there are no slots available.  This means that the worm head can exist,
  77.  *  it just cannot ever grow a tail.
  78.  *
  79.  *  It, also, means that there is an optimisation to made.  The [0] positions
  80.  *  of the arrays are never used.  Meaning, we really *could* have one more
  81.  *  tailed worm on the level, or use a smaller array (using wormno - 1).
  82.  *
  83.  *  Implementation is left to the interested hacker.
  84.  */
  85. int
  86. get_wormno()
  87. {
  88.     register int new_wormno = 1;
  89.  
  90.     while (new_wormno < MAX_NUM_WORMS) {
  91.     if (!wheads[new_wormno])
  92.         return new_wormno; /* found an empty wtails[] slot at new_wormno */
  93.     new_wormno++;
  94.     }
  95.  
  96.     return(0);    /* level infested with worms */
  97. }
  98.  
  99. /*
  100.  *  initworm()
  101.  *  
  102.  *  Use if (mon->wormno = get_wormno()) before calling this function!
  103.  *
  104.  *  Initialize the worm entry.  This will set up the worm grow time, and
  105.  *  create and initialize the dummy segment for wheads[] and wtails[].
  106.  *
  107.  *  If the worm has no tail (ie get_wormno() fails) then this function need
  108.  *  not be called.
  109.  */
  110. void
  111. initworm(worm, wseg_count)
  112.     struct monst *worm;
  113.     int wseg_count;
  114. {
  115.     register struct wseg *seg, *new_tail = create_worm_tail(wseg_count);
  116.     register int wnum = worm->wormno;
  117.  
  118. /*  if (!wnum) return; /* bullet proofing */
  119.  
  120.     if (new_tail) {
  121.     wtails[wnum] = new_tail;
  122.     for (seg = new_tail; seg->nseg; seg = seg->nseg);
  123.     wheads[wnum] = seg;
  124.     } else {
  125.         wtails[wnum] = wheads[wnum] = seg = newseg();
  126.     seg->nseg    = (struct wseg *) 0;
  127.     seg->wx      = worm->mx;
  128.     seg->wy      = worm->my;
  129.     }
  130.     wgrowtime[wnum] = 0L;
  131. }
  132.  
  133.  
  134. /*
  135.  *  toss_wsegs()
  136.  *  
  137.  *  Get rid of all worm segments on and following the given pointer curr.
  138.  *  The display may or may not need to be updated as we free the segments.
  139.  */
  140. static
  141. void
  142. toss_wsegs(curr, display_update)
  143.     register struct wseg *curr;
  144.     register boolean display_update;
  145. {
  146.     register struct wseg *seg;
  147.  
  148.     while (curr) {
  149.     seg = curr->nseg;
  150.  
  151.     /* remove from level.monsters[][] */
  152.  
  153.     /* need to check curr->wx for genocided while migrating_mon */
  154.     if (curr->wx) {
  155.         remove_monster(curr->wx, curr->wy);
  156.  
  157.         /* update screen before deallocation */
  158.         if (display_update) newsym(curr->wx,curr->wy);
  159.     }
  160.  
  161.     /* free memory used by the segment */
  162.     dealloc_seg(curr);
  163.     curr = seg;
  164.     }
  165. }
  166.  
  167.  
  168. /*
  169.  *  shrink_worm()
  170.  *
  171.  *  Remove the tail segment of the worm (the starting segment of the list).
  172.  */
  173. static
  174. void
  175. shrink_worm(wnum)
  176.     int wnum;    /* worm number */
  177. {
  178.     struct wseg *seg;
  179.  
  180.     if (wtails[wnum] == wheads[wnum]) return;    /* no tail */
  181.  
  182.     seg = wtails[wnum];
  183.     wtails[wnum] = seg->nseg;
  184.     seg->nseg = (struct wseg *) 0;
  185.     toss_wsegs(seg, TRUE);
  186. }
  187.  
  188. /*
  189.  *  worm_move()
  190.  * 
  191.  *  Check for mon->wormno before calling this function!
  192.  *
  193.  *  Move the worm.  Maybe grow.
  194.  */
  195. void
  196. worm_move(worm)
  197.     struct monst *worm;
  198. {
  199.     register struct wseg *seg, *new_seg;    /* new segment */
  200.     register int     wnum = worm->wormno;    /* worm number */
  201.  
  202.  
  203. /*  if (!wnum) return; /* bullet proofing */
  204.  
  205.     /*
  206.      *  Place a segment at the old worm head.  The head has already moved.
  207.      */
  208.     seg = wheads[wnum];
  209.     place_worm_seg(worm, seg->wx, seg->wy);
  210.     newsym(seg->wx,seg->wy);        /* display the new segment */
  211.  
  212.     /*
  213.      *  Create a new dummy segment head and place it at the end of the list.
  214.      */
  215.     new_seg       = newseg();
  216.     new_seg->wx   = worm->mx;
  217.     new_seg->wy   = worm->my;
  218.     new_seg->nseg = (struct wseg *) 0;
  219.     seg->nseg     = new_seg;        /* attach it to the end of the list */
  220.     wheads[wnum]  = new_seg;        /* move the end pointer */
  221.  
  222.  
  223.     if (wgrowtime[wnum] <= moves) {
  224.     if (!wgrowtime[wnum])
  225.         wgrowtime[wnum] = moves + rnd(5);
  226.     else
  227.         wgrowtime[wnum] += rn1(15, 3);
  228.     worm->mhp += 3;
  229.     if (worm->mhp > MHPMAX) worm->mhp = MHPMAX;
  230.     if (worm->mhp > worm->mhpmax) worm->mhpmax = worm->mhp;
  231.     } else
  232.     /* The worm doesn't grow, so the last segment goes away. */
  233.     shrink_worm(wnum);
  234. }
  235.  
  236. /*
  237.  *  worm_nomove()
  238.  * 
  239.  *  Check for mon->wormno before calling this function!
  240.  *
  241.  *  The worm don't move so it should shrink.
  242.  */
  243. void
  244. worm_nomove(worm)
  245.     register struct monst *worm;
  246. {
  247.     shrink_worm((int) worm->wormno);    /* shrink */
  248.  
  249.     if (worm->mhp > 3)
  250.     worm->mhp -= 3;        /* mhpmax not changed ! */
  251.     else
  252.     worm->mhp = 1;
  253. }
  254.  
  255. /*
  256.  *  wormgone()
  257.  *
  258.  *  Check for mon->wormno before calling this function!
  259.  *
  260.  *  Kill a worm tail.
  261.  */
  262. void
  263. wormgone(worm)
  264.     register struct monst *worm;
  265. {
  266.     register int wnum = worm->wormno;
  267.  
  268. /*  if (!wnum) return; /* bullet proofing */
  269.  
  270.     worm->wormno = 0;
  271.  
  272.     /*  This will also remove the real monster (ie 'w') from the its
  273.      *  position in level.monsters[][].
  274.      */
  275.     toss_wsegs(wtails[wnum], TRUE);
  276.  
  277.     wheads[wnum] = wtails[wnum] = (struct wseg *) 0;
  278. }
  279.  
  280. /*
  281.  *  wormhitu()
  282.  *
  283.  *  Check for mon->wormno before calling this function!
  284.  *
  285.  *  If the hero is near any part of the worm, the worm will try to attack.
  286.  */
  287. void
  288. wormhitu(worm)
  289.     register struct monst *worm;
  290. {
  291.     register int wnum = worm->wormno;
  292.     register struct wseg *seg;
  293.  
  294. /*  if (!wnum) return; /* bullet proofing */
  295.  
  296. /*  This does not work right now because mattacku() thinks that the head is
  297.  *  out of range of the player.  We might try to kludge, and bring the head
  298.  *  within range for a tiny moment, but this needs a bit more looking at
  299.  *  before we decide to do this.
  300.  */
  301.     for (seg = wtails[wnum]; seg; seg = seg->nseg)
  302.     if (distu(seg->wx, seg->wy) < 3)
  303.         (void) mattacku(worm);
  304. }
  305.  
  306. /*  cutworm()
  307.  *
  308.  *  Check for mon->wormno before calling this function!
  309.  *
  310.  *  When hitting a worm (worm) at position x, y, with a weapon (weap),
  311.  *  there is a chance that the worm will be cut in half, and a chance
  312.  *  that both halves will survive.
  313.  */
  314. void
  315. cutworm(worm, x, y, weap)
  316.     struct monst *worm;
  317.     xchar x,y;
  318.     struct obj *weap;
  319. {
  320.     register struct wseg  *curr, *new_tail;
  321.     register struct monst *new_worm;
  322.     int wnum = worm->wormno;
  323.     int cut_chance, new_wnum;
  324.  
  325. /*  if (!wnum) return; /* bullet proofing */
  326.  
  327.     if (x == worm->mx && y == worm->my) return;        /* hit on head */
  328.  
  329.     /* cutting goes best with a bladed weapon */
  330.     cut_chance = rnd(20);    /* Normally  1-16 does not cut */
  331.                 /* Normally 17-20 does */
  332.  
  333.     if (weap && is_blade(weap))    /* With a blade 1- 6 does not cut */
  334.     cut_chance += 10;    /*         7-20 does */
  335.  
  336.     if (cut_chance < 17) return;    /* not good enough */
  337.  
  338.     /* Find the segment that was attacked. */
  339.     curr = wtails[wnum];
  340.  
  341.     while ( (curr->wx != x) || (curr->wy != y) ) {
  342.     curr = curr->nseg;
  343.     if (!curr) {
  344.         impossible("cut_worm:  no segment at (%d,%d)", (int) x, (int) y);
  345.         return;
  346.     }
  347.     }
  348.  
  349.     /* If this is the tail segment, then the worm just loses it. */
  350.     if (curr == wtails[wnum]) {
  351.     shrink_worm(wnum);
  352.     return;
  353.     }
  354.  
  355.     /*
  356.      *  Split the worm.  The tail for the new worm is the old worm's tail.
  357.      *  The tail for the old worm is the segment that follows "curr", 
  358.      *  and "curr" becomes the dummy segment under the new head.
  359.      */
  360.     new_tail = wtails[wnum];
  361.     wtails[wnum] = curr->nseg;
  362.     curr->nseg = (struct wseg *) 0;    /* split the worm */
  363.  
  364.     /*
  365.      *  At this point, the old worm is correct.  Any new worm will have
  366.      *  it's head at "curr" and its tail at "new_tail".
  367.      */
  368.  
  369.     /* Sometimes the tail end dies. */
  370.     if (rn2(3) || !(new_wnum = get_wormno())) {
  371.     You("cut part of the tail off of %s.", mon_nam(worm));
  372.     toss_wsegs(new_tail, TRUE);
  373.     worm->mhp /= 2;
  374.     return;
  375.     }
  376.  
  377.     /* Create the second worm. */
  378.     new_worm  = newmonst(0);
  379.     *new_worm = *worm;            /* make a copy of the old worm */
  380.     new_worm->m_id = flags.ident++;    /* make sure it has a unique id */
  381.     new_worm->wormno = new_wnum;    /* affix new worm number */
  382.  
  383.     if (worm->mtame)
  384.     new_worm->mtame = (rn2(max(2 + u.uluck, 2)) ? worm->mtame : 0);
  385.     else
  386.     if (worm->mpeaceful)
  387.         new_worm->mpeaceful = (rn2(max(2 + u.uluck, 2)) ? 1 : 0);
  388.     set_malign(new_worm);
  389.  
  390.     new_worm->mxlth = new_worm->mnamelth = 0;
  391.     
  392.     /* Devalue the monster level of both halves of the worm. */
  393.     worm->m_lev = ((unsigned)worm->m_lev <= 3) ? 
  394.            (unsigned)worm->m_lev : max((unsigned)worm->m_lev - 2, 3);
  395.     new_worm->m_lev = worm->m_lev;
  396.  
  397.     /* Calculate the mhp on the new_worm for the (lower) monster level. */
  398.     new_worm->mhpmax = new_worm->mhp = d((int)new_worm->m_lev, 8);
  399.  
  400.     /* Calculate the mhp on the old worm for the (lower) monster level. */
  401.     if (worm->m_lev > 3) {
  402.     worm->mhpmax = d((int)worm->m_lev, 8);
  403.     if (worm->mhpmax < worm->mhp) worm->mhp = worm->mhpmax;
  404.     }
  405.  
  406.     /* Add new monster to mon chain. */
  407.     new_worm->nmon = fmon;
  408.     fmon = new_worm;
  409.  
  410.     /* Initialize the new worm. */
  411.     place_monster(new_worm, x, y);    /* put worm in level.monsters[][] */
  412.     newsym(x, y);            /* make sure new worm shows up */
  413.  
  414.     wtails[new_wnum] = new_tail;    /* We've got all the info right now */
  415.     wheads[new_wnum] = curr;        /* so we can do this faster than    */
  416.     wgrowtime[new_wnum] = 0L;        /* trying to call initworm().       */
  417.  
  418.     /* Place the new monster at all the segment locations. */
  419.     place_wsegs(new_worm);
  420.  
  421.     You("cut %s in half.", mon_nam(worm));
  422. }
  423.  
  424.  
  425. /*
  426.  *  see_wsegs()
  427.  *
  428.  *  Refresh all of the segments of the given worm.  This is only called
  429.  *  from see_monster() in display.c or when a monster goes minvis.  It
  430.  *  is located here for modularity.
  431.  */
  432. void
  433. see_wsegs(worm) 
  434.     struct monst *worm;
  435. {
  436.     struct wseg *curr = wtails[worm->wormno];
  437.  
  438. /*  if (!mtmp->wormno) return; /* bullet proofing */
  439.  
  440.     while (curr != wheads[worm->wormno]) {
  441.     newsym(curr->wx,curr->wy);
  442.     curr = curr->nseg;
  443.     }
  444. }
  445.  
  446.  
  447. /*
  448.  *  save_worm()
  449.  *  
  450.  *  Save the worm information for later use.  The count is the number
  451.  *  of segments, including the dummy.  Called from save.c.
  452.  */
  453. void
  454. save_worm(fd, mode)
  455.     int fd, mode;
  456. {
  457.     int i;
  458.     int count;
  459.     struct wseg *curr, *temp;
  460.  
  461.     for (i = 1; i < MAX_NUM_WORMS; i++) {
  462.     for (count = 0, curr = wtails[i]; curr; curr = curr->nseg) count++;
  463.  
  464.     /* Save number of segments */
  465.     bwrite(fd, (genericptr_t) &count, sizeof(int));
  466.  
  467.     /* Save segment locations of the monster. */
  468.     if (count) {
  469.         for (curr = wtails[i]; curr; curr = curr->nseg) {
  470.         bwrite(fd, (genericptr_t) &(curr->wx), sizeof(xchar));
  471.         bwrite(fd, (genericptr_t) &(curr->wy), sizeof(xchar));
  472.         }
  473.     }
  474.     }
  475.     bwrite(fd, (genericptr_t) wgrowtime, sizeof(wgrowtime));
  476.  
  477.     if (mode & FREE_SAVE) {
  478.     /* Free the segments only.  savemonchn() will take care of the
  479.      * monsters. */
  480.     for (i = 1; i < MAX_NUM_WORMS; i++) {
  481.         if (!(curr = wtails[i])) continue;
  482.  
  483.         while (curr) {
  484.         temp = curr->nseg;
  485.         dealloc_seg(curr);        /* free the segment */
  486.         curr = temp;
  487.         }
  488.         wheads[i] = wtails[i] = (struct wseg *) 0;
  489.     }
  490.     }
  491.  
  492. }
  493.  
  494. /*
  495.  *  rest_worm()
  496.  *
  497.  *  Restore the worm information from the save file.  Called from restore.c
  498.  */
  499. void
  500. rest_worm(fd)
  501.     int fd;
  502. {
  503.     int i, j, count;
  504.     struct wseg *curr, *temp;
  505.  
  506.     for (i = 1; i < MAX_NUM_WORMS; i++) {
  507.     mread(fd, (genericptr_t) &count, sizeof(int));
  508.     if (!count) continue;    /* none */
  509.  
  510.     /* Get the segments. */
  511.     for (curr = (struct wseg *) 0, j = 0; j < count; j++) {
  512.         temp = newseg();
  513.         temp->nseg = (struct wseg *) 0;
  514.         mread(fd, (genericptr_t) &(temp->wx), sizeof(xchar));
  515.         mread(fd, (genericptr_t) &(temp->wy), sizeof(xchar));
  516.         if (curr)
  517.         curr->nseg = temp;
  518.         else
  519.         wtails[i] = temp;
  520.         curr = temp;
  521.     }
  522.     wheads[i] = curr;
  523.     }
  524.     mread(fd, (genericptr_t) wgrowtime, sizeof(wgrowtime));
  525. }
  526.  
  527. /*
  528.  *  place_wsegs()
  529.  *
  530.  *  Place the segments of the given worm.  Called from restore.c
  531.  */
  532. void
  533. place_wsegs(worm) 
  534.     struct monst *worm;
  535. {
  536.     struct wseg *curr = wtails[worm->wormno];
  537.  
  538. /*  if (!mtmp->wormno) return; /* bullet proofing */
  539.  
  540.     while (curr != wheads[worm->wormno]) {
  541.     place_worm_seg(worm,curr->wx,curr->wy);
  542.     curr = curr->nseg;
  543.     }
  544. }
  545.  
  546. /*
  547.  *  remove_worm()
  548.  *
  549.  *  This function is equivalent to the remove_monster #define in
  550.  *  rm.h, only it will take the worm *and* tail out of the levels array.
  551.  *  It does not get rid of (dealloc) the worm tail structures, and it does
  552.  *  not remove the mon from the fmon chain.
  553.  */
  554. void
  555. remove_worm(worm)
  556.     register struct monst *worm;
  557. {
  558.     register struct wseg *curr = wtails[worm->wormno];
  559.  
  560. /*  if (!mtmp->wormno) return; /* bullet proofing */
  561.  
  562.     while (curr) {
  563.     remove_monster(curr->wx, curr->wy);
  564.     newsym(curr->wx, curr->wy);
  565.     curr = curr->nseg;
  566.     }
  567. }
  568.  
  569. /*
  570.  *  place_worm_tail_randomly()
  571.  *
  572.  *  Place a worm tail somewhere on a level behind the head.
  573.  *  This routine essentially reverses the order of the wsegs from head
  574.  *  to tail while placing them.
  575.  *  x, and y are most likely the worm->mx, and worm->my, but don't *need* to
  576.  *  be, if somehow the head is disjoint from the tail.
  577.  */
  578. void
  579. place_worm_tail_randomly(worm, x, y)
  580.     struct monst *worm;
  581.     xchar x, y;
  582. {
  583.     int wnum = worm->wormno;
  584.     struct wseg *curr = wtails[wnum];
  585.     struct wseg *new_tail;
  586.     register xchar ox = x, oy = y;
  587.  
  588. /*  if (!wnum) return; /* bullet proofing */
  589.  
  590.     if (wnum && (!wtails[wnum] || !wheads[wnum]) ) {
  591.     impossible("place_worm_tail_randomly: wormno is set without a tail!");
  592.     return;
  593.     }
  594.  
  595.     wheads[wnum] = new_tail = curr;
  596.     curr = curr->nseg;
  597.     new_tail->nseg = (struct wseg *) 0;
  598.     new_tail->wx = x;
  599.     new_tail->wy = y;
  600.  
  601.     while(curr)  {
  602.     xchar nx, ny;
  603.     char tryct = 0;
  604.  
  605.     /* pick a random direction from x, y and search for goodpos() */
  606.  
  607.     do {
  608.         random_dir(ox, oy, &nx, &ny);
  609.     } while (!goodpos(nx, ny, worm, worm->data) && (tryct++ < 50));
  610.  
  611.     if (tryct < 50)  {
  612.         place_worm_seg(worm, nx, ny);
  613.         curr->wx = ox = nx;
  614.         curr->wy = oy = ny;
  615.         wtails[wnum] = curr;
  616.         curr = curr->nseg;
  617.         wtails[wnum]->nseg = new_tail;
  618.         new_tail = wtails[wnum];
  619.         newsym(nx, ny);
  620.     } else {            /* Oops.  Truncate because there was */
  621.         toss_wsegs(curr, FALSE);    /* no place for the rest of it */
  622.         curr = (struct wseg *) 0;
  623.     }
  624.     }
  625. }
  626.  
  627. /*
  628.  * Given a coordinate x, y.
  629.  * return in *nx, *ny, the coordinates of one of the <= 8 squares adjoining.
  630.  *
  631.  * This function, and the loop it serves, could be eliminated by coding
  632.  * enexto() with a search radius.
  633.  */
  634. static
  635. void
  636. random_dir(x, y, nx, ny)
  637.     register xchar   x,   y;
  638.     register xchar *nx, *ny;
  639. {
  640.     *nx = x;
  641.     *ny = y;
  642.  
  643.     *nx += (x > 1 ?            /* extreme left ? */
  644.         (x < COLNO ?         /* extreme right ? */
  645.             (rn2(3) - 1)      /* neither so +1, 0, or -1 */
  646.         :    -rn2(2))     /* 0, or -1 */
  647.        :    rn2(2));        /* 0, or 1 */
  648.  
  649.     *ny += (*nx == x ?            /* same kind of thing with y */
  650.         (y > 1 ?
  651.             (y < ROWNO ?
  652.             (rn2(2) ?
  653.                 1
  654.             :   -1)
  655.             :    -1)
  656.         :   1) 
  657.         :    (y > 1 ?
  658.             (y < ROWNO ?
  659.             (rn2(3) - 1)
  660.             :    -rn2(2))
  661.         :   rn2(2)));
  662. }
  663.  
  664. /*  count_wsegs()
  665.  *
  666.  *  returns
  667.  *  the number of visible segments that a worm has.
  668.  */
  669.  
  670. int
  671. count_wsegs(mtmp)
  672.     struct monst *mtmp;
  673. {
  674.     register int i=0;
  675.     register struct wseg *curr = (wtails[mtmp->wormno])->nseg;
  676.  
  677. /*  if (!mtmp->wormno) return 0; /* bullet proofing */
  678.  
  679.     while (curr) {
  680.     i++;
  681.     curr = curr->nseg;
  682.     }
  683.  
  684.     return i;
  685. }
  686.  
  687. /*  create_worm_tail()
  688.  *
  689.  *  will create a worm tail chain of (num_segs + 1) and return a pointer to it.
  690.  */
  691. static
  692. struct wseg *
  693. create_worm_tail(num_segs)
  694.     int num_segs;
  695. {
  696.     register int i=0;
  697.     register struct wseg *new_tail, *curr;
  698.  
  699.     if (!num_segs) return (struct wseg *)0;
  700.  
  701.     new_tail = curr = newseg();
  702.     curr->nseg = (struct wseg *)0;
  703.     curr->wx = 0;
  704.     curr->wy = 0;
  705.  
  706.     while (i < num_segs) {
  707.     curr->nseg = newseg();
  708.     curr = curr->nseg;
  709.     curr->nseg = (struct wseg *)0;
  710.     curr->wx = 0;
  711.     curr->wy = 0;
  712.     i++;
  713.     }
  714.  
  715.     return (new_tail);
  716. }
  717.  
  718. /*worm.c*/
  719.